﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ActiproSoftware.Windows.Controls.PropertyGrid;
using EditorExe.StepRequestDialogs;
using ExpressionTreeLib;
using MS.Internal.Controls;

namespace EditorExe
{
    class ServiceProvider  : IServiceProvider
    {
        private readonly ContentControl _detailControl;
        private readonly TreeView _treeView;

        public ServiceProvider(ContentControl detailControl, TreeView treeView)
        {
            _detailControl = detailControl;
            _treeView = treeView;
        }

        public object GetService(Type serviceType)
        {
            if (serviceType.Equals(typeof(IEvaluateProvider)))
                return new EvaluateArgumentsProvider();

            if (serviceType.Equals(typeof(IRequestNewNodeType)))
                return new RequestNewNodeType();

            if (serviceType.Equals(typeof(IDetailViewService)))
                return new DetailViewService(_detailControl);

            if (serviceType.Equals(typeof(ITreeViewService)))
                return new TreeViewService(this._treeView);

            if (serviceType.Equals(typeof(IShowMessage)))
                return new ShowMessage();

            if (serviceType.Equals(typeof(IStepRequest<Type>)))
                return new RequestClrType();

            if (serviceType.Equals(typeof(IStepRequest<ParameterExpression[]>)))
                return new RequestParameters();

            if (serviceType.Equals(typeof(IStepRequest<LongText>)))
                return new RequestLongText();

            return null;
        }

        internal class ShowMessage : IShowMessage
        {
            public void Show(string message)
            {
                new Window() {Content = new TextBox {Text = message, Margin = new Thickness(2), IsReadOnly = true }}.ShowDialog();
            }
        }

        internal class TreeViewService : ITreeViewService
        {
            private readonly TreeView _treeView;

            public TreeViewService(TreeView treeView)
            {
                _treeView = treeView;
            }

            public void Select(NodeViewModel nodeViewModel)
            {
                this.Find(this._treeView, nodeViewModel).IsSelected = true;
            }

            TreeViewItem Find(ItemsControl itemsControl, NodeViewModel nodeViewModel)
            {
                var treeViewItem = itemsControl.ItemContainerGenerator.ContainerFromItem(nodeViewModel) as TreeViewItem;
                if (treeViewItem != null)
                    return treeViewItem;
                foreach (var item in itemsControl.Items)
                {
                    var t = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as ItemsControl;
                    var treev = this.Find(t, nodeViewModel);
                    if (treev != null) return treev;
                }

                return null;
            }
        }

        internal class DetailViewService : IDetailViewService
        {
            private readonly ContentControl _detailControl;

            public DetailViewService(ContentControl detailControl)
            {
                _detailControl = detailControl;
            }

            public void Reload()
            {
                var template = this._detailControl.Resources.Values.OfType<DataTemplate>().FirstOrDefault();
                if( VisualTreeHelper.GetChildrenCount(this._detailControl) == 0 )
                    return;

                var contentPresenter = VisualTreeHelper.GetChild(this._detailControl, 0) as ContentPresenter;

                var propgd = template.FindName("pg", contentPresenter) as PropertyGrid;
                propgd.Refresh();
            }
        }

        internal class RequestNewNodeType : IRequestNewNodeType
        {
            public Type GetNewNodeType()
            {
                var dialog = new NewExpressionNodeDialog();

                var dialogResult = dialog.ShowDialog();
                if( dialogResult.HasValue && dialogResult.Value )
                    return dialog.Selected;

                return null;
            }
        }

    }
}
